﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Design;
using System.Data.Metadata.Edm;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using EnvDTE;

namespace EntityFrameworkContrib.Design.VisualStudio.Testing
{
	class Parser
	{
		static readonly string 
			_conceptualModelsNodeName = "ConceptualModels",
			_edmNamespace = "http://schemas.microsoft.com/ado/2006/04/edm",
			_edmxNamespace = "http://schemas.microsoft.com/ado/2007/06/edmx",
			_edmxNodeName = "Edmx",
			_runtimeNodeName = "Runtime",
			_schemaNodeName = "Schema";

		public string Parse( string inputFileContent )
		{
			// IVsSolution globalService = Package.GetGlobalService( typeof(SVsOutputWindow) ) as IVsSolution;
            // IVsHierarchy vsHierarchy = VsUtils.GetVsHierarchy(base.ProjectItem.ContainingProject, globalService);
            // uint projectItemId = VsUtils.GetProjectItemId(vsHierarchy, base.ProjectItem);
            /*EdmErrorList errorList = ErrorListHelper.GetErrorList(vsHierarchy, projectItemId);
            errorList.RemoveItems(typeof(SfgErrorTask));*/
            XmlNamespaceManager nsMgr = new XmlNamespaceManager( new NameTable() );
            nsMgr.AddNamespace("edmx", _edmxNamespace);
            nsMgr.AddNamespace("edm", _edmNamespace);
            XmlParserContext inputContext = new XmlParserContext( null, nsMgr, null, XmlSpace.Preserve );
        	IList<EdmSchemaError> list2 = new List<EdmSchemaError>();
            using ( StringReader reader = new StringReader( inputFileContent ) )
            {
            	using ( XmlReader reader2 = XmlReader.Create( reader, null, inputContext ) )
                {
                    if ( NavigateToConceptualModelsSchemaElement(reader2) )
                    {
                    	using ( StringReader reader3 = new StringReader( reader2.ReadOuterXml() ) )
                        {
                        	int num2 = GetLineInfo( reader2 ) - 1;
                            XmlReaderSettings settings = new XmlReaderSettings { LineNumberOffset = num2 };
                            using ( XmlReader reader4 = XmlReader.Create( reader3, settings, inputContext ) )
                            {
                                using ( StringWriter writer = new StringWriter( CultureInfo.InvariantCulture ) )
                                {
                                	EntityClassGenerator generator = new EntityClassGenerator( LanguageOption.GenerateCSharpCode );
									PluginManager manager = new PluginManager( null );
									manager.Broadcast( generator );
                                    generator.GenerateCode( reader4, writer );
                                    return writer.ToString();
                                }
                            }
                        }
                    }
                }
            }			
			return null;
		}

		static int GetLineInfo(XmlReader reader)
        {
            IXmlLineInfo info = reader as IXmlLineInfo;
            if ((info != null) && info.HasLineInfo())
            {
                return info.LineNumber;
            }
            return 0;
        }

        static bool NavigateToConceptualModelsSchemaElement(XmlReader reader)
        {
            if (!NavigateToElementWithinParent(reader, _edmxNodeName, _edmxNamespace, null, null))
            {
                return false;
            }
            if (!NavigateToElementWithinParent(reader, _runtimeNodeName, _edmxNamespace, _edmxNodeName, _edmxNamespace))
            {
                return false;
            }
            if (!NavigateToElementWithinParent(reader, _conceptualModelsNodeName, _edmxNamespace, _runtimeNodeName, _edmxNamespace))
            {
                return false;
            }
            if (!NavigateToElementWithinParent(reader, _schemaNodeName, _edmNamespace, _conceptualModelsNodeName, _edmxNamespace))
            {
                return false;
            }
            return true;
        }

        private static bool NavigateToElementWithinParent(XmlReader reader, string localName, string namespaceURI, string parentLocalName, string parentNamespaceURI)
        {
            bool flag = (parentLocalName != null) && (parentNamespaceURI != null);
            while (!reader.EOF)
            {
                if ((flag && (XmlNodeType.EndElement == reader.NodeType)) && ((reader.LocalName == parentLocalName) && (reader.NamespaceURI == parentNamespaceURI)))
                {
                    return false;
                }
                if (((XmlNodeType.Element == reader.NodeType) && (reader.LocalName == localName)) && (reader.NamespaceURI == namespaceURI))
                {
                    return true;
                }
                reader.Read();
            }
            return false;
        }

	}
}
